#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <math.h>
#include "bf.h"

bf_stream bf_stream_new (int fd) {
  bf_stream this = (bf_stream) malloc (sizeof (struct _bitiob));
  this->base = (char*) malloc (sizeof (char) * BUFFSIZE / 8);
  this->fd = fd;
  this->ptr = this->base;
  this->count = 0;
  return this;
}

void bf_fillbuff (bf_stream bf) {
  bf->count = read (bf->fd, bf->base, BUFFSIZE / 8);
  if (bf->count == -1) {
    fprintf (stderr, "ERROR reading input file. Aborting\n");
    exit (EXIT_FAILURE);
  }
  fprintf (stderr, "Fillbuf  count %d , data %s\n", bf->count, bf->base);
  bf->count *= 8;
}

void bf_flush (bf_stream bf) {
  int r;
  fprintf (stderr, "Flush  count : %d, data %s\n", bf->count, bf->base);
  bf->count /= 8;
  while (bf->count && ((r = write (bf->fd, bf->base, bf->count)) != -1))
    bf->count -= r;  
}

void putbit (bf_stream bf, int b) {
  int q, r;
  q = bf->count / 8; r = 7 - bf->count % 8;
  if (b) bf->base[q] |= (1 << r);
  else bf->base[q] &= ~(1 << r);
  if (++bf->count == BUFFSIZE)
    bf_flush (bf);
}

int getbit (bf_stream bf) {
  int q, r;
  if (bf->count == 0)
    bf_fillbuff (bf);
  if (bf->count == 0) return EOF;
  bf->count--;
  q = bf->count / 8; r = bf->count % 8;
  return   ((bf->base[q] >> r) & 1);
}

/*int main (int argc, char *argv[]) {
  int fd;
  int c = 'a', i, b;
  bf_stream bf;

  fd = open (argv[1], O_RDWR | O_CREAT | O_TRUNC, 0644);
  bf = bf_stream_new (fd);

  for (i = 7; i >= 0; i--) {
    putbit (bf, (c >> i) & 1);
    putchar (((c >> i) & 1) ? '1' : '0');
  }
  c = 'b';
  for (i = 7; i >= 0; i--) {
    putbit (bf, (c >> i) & 1);
    putchar (((c >> i) & 1) ? '1' : '0');
  }
  
  bf_flush (bf);
  close (fd);

  puts ("ALO");

  fd = open (argv[1], O_RDONLY, 0644);
  bf = bf_stream_new (fd);
  
  c = 0;
  for (i = 7; i >= 0; i--) {
    b = getbit (bf);
    putchar(b ? '1' : '0');
    c += b * pow (2, i);
  }
  putchar (' ');
  putchar (c);
  putchar ('\n');

  c = 0;
  for (i = 7; i >= 0; i--) {
    b = getbit (bf);
    putchar(b ? '1' : '0');
    c += b * pow (2, i);
  }
  putchar (' ');
  putchar (c);
  putchar ('\n');

  close (fd);

  return (EXIT_SUCCESS);
}
*/
